/*
 * @Author: 因吹斯婷 3575377636@qq.com
 * @Date: 2025-06-27 10:17:17
 * @LastEditors: 因吹斯婷 3575377636@qq.com
 * @LastEditTime: 2025-06-28 16:51:16
 * @FilePath: \23见习2\Calculator.java
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.awt.BorderLayout;//默认布局管理器
import java.awt.GridLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.awt.Color;
import javax.swing.Timer;
//继承JFrame,为了直接复用swing框架中窗口管理的能力
//为了子类可以直接调用JFrame public方法
//ActionListener是java中事件处理机制的核心部分
//为了建立计算器组件和用户操作之间的响应机制
public class Calculator extends JFrame implements ActionListener{
    //声明界面组件
    // //上下两个面板，上面是文本框区域，下面是按钮区域
    private JPanel north,center;
    //文本框，显示计算过程、结果或者日期时间
    private JTextField field;
    //按钮
    private JButton[] btns;
    // 保存时间显示前的文本
    private String timeDisplayText = "";
    // 定时更新时间的计时器
    private Timer timeTimer; 
    // 标记是否正在显示时间 
    private boolean isShowingTime = false; 

    //初始化窗口-构造器，构造方法,无参构造器
    public  Calculator(){
        //设置窗口标题
        setTitle("计算器");
        //设置窗口大小
        setSize(700,700);
        //设置窗口关闭时程序
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        //设置窗口居中显示
        setLocationRelativeTo(null);
        //初始化界面组件
        initComponent();
        //设置窗口显示
        setVisible(true);
    }

    //初始化界面组件
    private void initComponent(){
        //创建面板容器
        //文本框区域，按钮区域
        north=new JPanel();
        //容器面板 按钮区域
        center=new JPanel();
        //文本框，显示计算过程、结果或者日期时间
        field=new JTextField();
        //设置输入框大小，首选尺寸
        field.setPreferredSize(new Dimension(700,150));
        //禁用文字输入，禁止通过电脑键盘输入编辑
        field.setEditable(false);
        //设置输入框文字大小
        field.setFont(new Font("SansSerif",Font.BOLD,35));
        
        // 设置背景颜色
        getContentPane().setBackground(new Color(230, 240, 255)); // 主窗口背景
        north.setBackground(new Color(200, 220, 245)); //顶部面板背景（文本框）
        center.setBackground(new Color(200, 220, 245)); //中部面板背景（按钮）
        
        // 设置文本框样式
        field.setPreferredSize(new Dimension(700, 150));
        field.setEditable(false);
        field.setFont(new Font("SansSerif", Font.BOLD, 35));
        field.setBackground(new Color(255, 255, 255)); //文本框背景
        field.setForeground(new Color(0, 0, 0)); //文本颜色
        field.setHorizontalAlignment(JTextField.RIGHT); //文本右对齐

        //按钮文本内容
        String[] str=new String[]{
           "7","8","9","+",
           "4","5","6","-",
           "1","2","3","×",
           "0",".","=","÷",
           "C","B","T","S"
        };
        //按钮数组
        btns=new JButton[str.length];
        for(int i=0;i<btns.length;i++){
            btns[i]=new JButton(str[i]);
            //按钮字体，加粗，大小
            btns[i].setFont(new Font("SansSerif",Font.BOLD,25));
            // 设置按钮样式
            btns[i].setForeground(new Color(0, 0, 0));
            // 按钮文本颜色
            // 根据按钮类型设置不同背景颜色
            if (i >= 16) { // 功能按钮 (C, B, T, S)
                btns[i].setBackground(new Color(255, 170, 170)); // 红色系
            } else if (i % 4 == 3) { // 运算符按钮 (+, -, ×, ÷, =)
                btns[i].setBackground(new Color(170, 210, 255)); // 蓝色系
            } else { // 数字按钮
                btns[i].setBackground(new Color(220, 255, 220)); // 绿色系
            }
            
            // 设置按钮边框效果
            btns[i].setBorderPainted(true);
            btns[i].setFocusPainted(false);
        }
        //将组件放到窗口中
        //设置布局管理器
        //north是顶部面板，使用BorderLayout布局
        north.setLayout(new BorderLayout());
        //center中间面板，使用5行4列网格布局
        center.setLayout(new GridLayout(5,4));
        //组件设置
        //field文本框添加到 north顶部面板，使用BorderLayout居中
        north.add(field,BorderLayout.CENTER);
        //btns 按钮添加到center面板，增强for循环
        for(JButton btn:btns){
            //通过遍历将所有按钮添加到center面板
            center.add(btn);
        }
        //将north顶部面板添加到窗口中
        add(north,BorderLayout.NORTH);
        //将center面板添加到窗口中
        add(center);
        //绑定按钮的监听事件
        for(JButton btn:btns){
            //this代表当前对象实例
            btn.addActionListener(this);
        }
        //初始化时间定时器（每秒更新一次）
        timeTimer = new Timer(1000,(ActionEvent e)-> {
            if (isShowingTime) {
                LocalDateTime now = LocalDateTime.now();
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                field.setText(now.format(formatter));
            }
        });
        timeTimer.start();
    }

    //执行计算功能
    //使用private，封装特性，保证内部结构的安全性，防止其他任意调用
    private void calculate(){
        //用户输入1+1，执行计算操作，然后将结果展示到文本框上
        //用户输入1+1
        //如果表达式里有 × ÷ 要替换为 *和 /
        String expression=field.getText();
        expression=expression.replace("×","*").replace("÷","/");
        //执行计算操作，使用js计算引擎（封装代码）
        ScriptEngineManager manager=new ScriptEngineManager();
        //初始化计算引擎，使用javascript解析数学表达式
        ScriptEngine engine=manager.getEngineByName("javascript");
        try{//try中放的是可能出现异常的代码
        //开始计算，计算过程可能异常，这里需要处理异常
        Object result=engine.eval(expression);
        //将结果展示到文本框
        field.setText(result.toString()); 
        isShowingTime = false; // 计算后停止显示时间
        }
        //catch中放的是异常处理方式
        catch(ScriptException e){
             field.setText("运算错误");
            e.printStackTrace();
        } 
    }
    //计算平方根的方法
    private void calculateSquareRoot() {
        try {
            String input=field.getText();
            double number=Double.parseDouble(input);
            
            if (number<0) {
                field.setText("错误：负数不能开平方");
                return;
            }
            double result=Math.sqrt(number);
            field.setText(String.valueOf(result));
            isShowingTime = false; //计算后停止显示时间
        } catch (NumberFormatException e) {
            field.setText("格式错误");
        }
    }

    //实现接口中的抽象方法，处理事件（注解和代码不要隔开）
    @Override
    public void actionPerformed(ActionEvent a){
        //此处可以捕获到ActionListener监听的事件
        //获取被点击的按钮或者按钮的文字
        Object source=a.getSource();
        if(source instanceof JButton){
            JButton btn=(JButton)source;
            String text=btn.getText();
            //处理对应按键的文字
            setBtnText(text);
        }
    }

    //处理对应按键文本
    private void setBtnText(String text){
        String oldText = field.getText();
        //如果当前显示时间，点击数字/运算符时切换到计算模式
        //if (isShowingTime) {
            //timeDisplayText = oldText; // 保存当前时间显示
            //isShowingTime = false;     // 关闭时间显示模式
            //oldText="";              // 清空输入框以开始新计算
        //}
        switch(text){
            case "C":
                //清空功能
                field.setText("");
                // 清空时间显示缓存
                timeDisplayText = ""; 
                 isShowingTime = false; // 清空时停止时间显示
                break;
            case "B":
                //退格功能
                //1.获取输入框的内容，截取最后一个字符串
                String numText=field.getText();
                //两种情况：空或有内容 isEmpty（），返回值为boolean类型
                if(numText.length()!=0){
                    //输入框内容不为空
                     //System.out.println("输入的内容不为空"+numText);
                     //numText的长度-1
                     String lastText=numText.substring(0,numText.length()-1);
                     //System.out.println("lastText:"+lastText);
                     //将截取的文本设置到文本框
                     field.setText(lastText);
                }
                else{
                    //输入内容为空
                }
                break;
            case "T":
                //切换时间显示状态
                if (isShowingTime) {
                    // 退出时间显示，恢复之前的计算内容
                    isShowingTime=false;
                    field.setText(timeDisplayText);
                } else {
                    //开始显示时间，保存当前计算内容
                    timeDisplayText=field.getText();
                    isShowingTime=true;
                    field.setText(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                }
                break;

            case "S":
                //计算平方根
                calculateSquareRoot();
                break;
            case "=":
                calculate();
                break;
            default: 
                //String oldText=field.getText();
                // 如果当前显示时间，点击数字时先清除时间
                if (!timeDisplayText.isEmpty()) {
                    oldText = timeDisplayText;
                    timeDisplayText = "";
                }
                //输入框中的操作符不能连续出现，小数点不能连续出现，操作符不能出现在数字前面
                //检查是否是操作符
                boolean isOperator = text.equals("+") || text.equals("-") || text.equals("×") || text.equals("÷");
                //防止操作符出现在数字前面（表达式为空时不能输入操作符）
                if (isOperator && oldText.isEmpty()) {
                    return;
                }
                //防止操作符连续出现
                if (isOperator && oldText.length() > 0) {
                    char lastChar = oldText.charAt(oldText.length() - 1);
                    if (lastChar == '+' || lastChar == '-' || lastChar == '×' || lastChar == '÷') {
                        return;
                    }
                }
                //防止小数点连续出现
                if (text.equals(".") && oldText.contains(".")) {
                    //检查最后一个数字是否已经包含小数点
                    String[] parts = oldText.split("[+\\-×÷]");
                    String lastNumber = parts[parts.length - 1];
                    if (lastNumber.contains(".")) {
                        return;
                    }
                }
                //处理0的特殊情况
                if (text.equals("0")) {
                // 防止多个前导0（除非有小数点）
                if (oldText.equals("0")) return;
                // 允许0出现在小数点后或运算符后
                if (!oldText.isEmpty()) {
                    char lastChar = oldText.charAt(oldText.length()-1);
                    if (lastChar == '0' && !oldText.contains(".")) return;
                }
            }
                //如果前面没有数字，按下小数点，自动补充为 0.
                if(text.equals(".")&&oldText.isEmpty()){
                    field.setText("0.");
                }else{
                    field.setText(oldText+text);
                }
                break;     
        }
    }
    public static void main(String[] args){
        //创建类的对象-这样写线程不安全
        //是Java开发中保证线程安全的核心代码
        SwingUtilities.invokeLater(Calculator::new);
    }
}
